package one.stand.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.vioao.wechat.api.component.ComponentApi;
import com.github.vioao.wechat.bean.response.BaseResponse;
import com.github.vioao.wechat.bean.response.component.*;
import com.github.vioao.wechat.bean.response.component.wxa.template.LibraryAddResponse;
import one.stand.code.RedisCode;
import one.stand.enums.EnumUtil;
import one.stand.enums.LoginEnum;
import one.stand.enums.WxNoticeEnums;
import one.stand.code.RedisCode;
import one.stand.domain.NewLibraryAddResponse;
import one.stand.enums.EnumUtil;
import one.stand.enums.LoginEnum;
import one.stand.enums.WxSubscribeEnums;
import one.stand.model.*;
import one.stand.request.CompanyAccountRequest;
import one.stand.service.CodeService;
import one.stand.service.ComponentService;
import one.stand.service.DomainService;
import one.stand.service.TemplateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author: QIK
 * @CreateDate: 2019/5/9 10:22
 */
@Service
@Transactional
public class ComponentServiceImpl extends PublicBaseService implements ComponentService {
    @Autowired
    private ComponentApi componentApi;
    @Lazy
    @Autowired
    private DomainService domainService;
    @Lazy
    @Autowired
    private CodeService codeService;

    @Override
    public String getComponentToken() {
        String ticket = redisUtil.get(RedisCode.getTicket(componentConfig.getAppid()));
        String key = RedisCode.getComponentTokenKey(componentConfig.getAppid());
        String token = redisUtil.get(key);
        if (null == token) {
            GetComponentTokenResponse getComponentTokenResponse = componentApi.getComponentToken(componentConfig.getAppid(), componentConfig.getSecret(), ticket);
            log.info("response:{},ticket:{},key:{},token:{},confgiappid:{}",getComponentTokenResponse,ticket,key,token,componentConfig.getAppid());
            if (getComponentTokenResponse.isSuccess()) {
                token = getComponentTokenResponse.getComponentAccessToken();
                redisUtil.set(key, token, 100, TimeUnit.MINUTES);
            }
            log.info("componentToken:{}", JSON.toJSONString(getComponentTokenResponse));
        }
        return token;
    }

    @Override
    public void refreshSubscribeTemplates() {
        List<CompanyAccountModel> accountModels = companyAccountMapper.selectCrmAndUserList();
        accountModels.forEach(t -> addTemplate(t));
    }

    @Override
    public String createPreAuthCode() {
        String code = null;
        CreatePreAuthCodeResponse createPreAuthCodeResponse = componentApi.createPreAuthCode(getComponentToken(), componentConfig.getAppid());
        if (createPreAuthCodeResponse.isSuccess()) {
            code = createPreAuthCodeResponse.getPreAuthCode();
        }
        return code;
    }

    @Override
    public ResultModel<String> componentloginpage(CompanyAccountRequest request) {
        log.info("第三方平台授权页面：请求参数：{}", JSON.toJSONString(request));
        if (request == null) {
            return ResultModel.checkParamFail();
        } else if (StringUtils.isEmpty(request.getAppId())) {
            return ResultModel.checkParamFail("appId: AppId为空");
        } else if (null == request.getAccountType()) {
            return ResultModel.checkParamFail("accountType: AccountType为空");
        } else if (StringUtils.isEmpty(request.getAppSecret())) {
            return ResultModel.checkParamFail("appSecret: AppSecret为空");
        } else if (StringUtils.isEmpty(request.getAppName())) {
            return ResultModel.checkParamFail("appName: AppName");
        }
        CompanyAccountModel model = companyAccountMapper.select(new CompanyAccountModel() {{
            setCompanyId(request.getCId().intValue());
            setAccountType(request.getAccountType());
        }});
        log.info("获取授权码：{}", JSON.toJSONString(model));
        if (null != model) {
            if (model.getState() == 1) {
                return ResultModel.fail("您已经认证成功，无需再次认证");
            }
            model.setAppId(request.getAppId());
            model.setAppSecret(request.getAppSecret());
            companyAccountMapper.updateByPrimaryKeySelective(model);
        }
        if (model == null) {
            CompanyModel companyModel = companyMapper.selectByPrimaryKey(request.getCId().intValue());
            model = new CompanyAccountModel();
            model.setAppId(request.getAppId());
            model.setAccountType(request.getAccountType());
            model.setCreateTime(currentDate());
            model.setCompanyId(request.getCId().intValue());
            model.setCompanyKey(companyModel.getCompanyKey());
            model.setAppName(request.getAppName());
            model.setAppSecret(request.getAppSecret());
            companyAccountMapper.insertSelective(model);
        }
        StringBuffer stringBuffer = new StringBuffer(componentApi.getComponentLoginPage(componentConfig.getAppid(), createPreAuthCode(), componentConfig.getRedirectUri(), "3", request.getAppId()));
        stringBuffer.append("&type=").append(request.getAccountType());
        return ResultModel.success(stringBuffer.toString());
    }

    @Override
    public QueryAuthResponse queryAuth(String code) {
        QueryAuthResponse respons = componentApi.queryAuth(getComponentToken(), componentConfig.getAppid(), code);
        return respons;
    }

    @Override
    public ResultModel getAuthorizerInfo(CompanyAccountRequest request) {
        if (StringUtils.isEmpty(request.getAppId())) {
            return ResultModel.checkParamFail("appId: AppId为空");
        }
        String key = RedisCode.getAuthorizerRefreshTokenKey(request.getAppId());
        String token = getComponentToken();
        GetAuthorizerInfoResponse response = componentApi.getAuthorizerInfo(token, componentConfig.getAppid(), request.getAppId());
        QueryAuthResponse info = response.getAuthorizationInfo();
        if (response.isSuccess()) {
            token = response.getAuthorizationInfo().getAuthorizerAccessToken();
            if (StringUtils.isEmpty(token)) {
                token = response.getAuthorizationInfo().getAuthorizerRefreshToken();
            }
            redisUtil.set(key, token);

        }
        info.setAppid(null);
        info.setAuthorizerAccessToken(null);
        info.setAuthorizerRefreshToken(null);
        response.setAuthorizationInfo(info);
        return ResultModel.success(response);
    }

    @Override
    public String getAuthorizerRefreshToken(String appid) {
        String key = RedisCode.getAuthorizerRefreshTokenKey(appid);
        String token = redisUtil.get(key);
        if (StringUtils.isEmpty(token)) {
            log.info("token:{},appid:{}, componentConfig:{}",token,appid, componentConfig.getAppid());
            GetAuthorizerInfoResponse response = componentApi.getAuthorizerInfo(getComponentToken(), componentConfig.getAppid(), appid);
            if (response.isSuccess()) {
                token = response.getAuthorizationInfo().getAuthorizerAccessToken();
                if (StringUtils.isEmpty(token)) {
                    token = response.getAuthorizationInfo().getAuthorizerRefreshToken();
                }
                redisUtil.set(key, token, 10, TimeUnit.MINUTES);

            }
            log.info("获取代理小程序账号信息：{}", JSON.toJSONString(response));
        }
        return token;
    }

    @Override
    public String getAuthorizerToken(String appid) {
        String token = redisUtil.get(RedisCode.getAuthorizerToken(appid));
        if (StringUtils.isEmpty(token)) {
            GetAuthorizerTokenResponse getAuthorizerTokenResponse = componentApi.getAuthorizerToken(getComponentToken(), componentConfig.getAppid(), appid, getAuthorizerRefreshToken(appid));
            log.info("getAuthorizerTokenResponse:{},token:{},appid:{}",getAuthorizerTokenResponse,token,appid);
            if (getAuthorizerTokenResponse.isSuccess()) {
                token = getAuthorizerTokenResponse.getAuthorizerAccessToken();
                redisUtil.set(RedisCode.getAuthorizerToken(appid), token, 100, TimeUnit.MINUTES);
            }
        }
        return token;
    }

    @Override
    public ResultModel componentCallBack(CompanyAccountRequest request) {
        if (request == null) {
            return ResultModel.checkParamFail();
        } else if (StringUtils.isEmpty(request.getAuthCode())) {
            return ResultModel.checkParamFail("authCode: AuthCode为空");
        } else if (StringUtils.isEmpty(request.getAppId())) {
            return ResultModel.checkParamFail("appId: AppId为空");
        }
        QueryAuthResponse response = queryAuth(request.getAuthCode());
        log.info("授权成功后返回数据：{}", JSON.toJSONString(response));
        if (!response.getErrcode().equals(0)) {
            return ResultModel.fail("授权返回失败：" + response.getErrmsg());
        }
        String token = getAuthorizerToken(request.getAppId());
        log.info("获取代理小程序Token:{}", token);
        CompanyAccountModel model = companyAccountMapper.select(new CompanyAccountModel() {{
            setAppId(request.getAppId());
        }});
        if (null != model) {
            model.setState(1);
            companyAccountMapper.updateByPrimaryKeySelective(model);
        } else {
            log.info("授权回调，未查到账号信息。。。。。。。。。。。。。");
            return ResultModel.fail("未查到账号信息");
        }
        BaseResponse baseResponse = domainService.modifyDomain(request.getAppId());
        log.info("授权后设置白名单：{}", baseResponse.toString());
        addTemplate(model);

        //验证是否绑定完两个小程序
        List<CompanyAccountModel> accountModelList = companyAccountMapper.selectProgramByCompanyId(new CompanyAccountModel() {{
            setCompanyId(model.getCompanyId().intValue());
        }});
        if (null == accountModelList || accountModelList.size() != 2) {
            log.info("小程序账号不齐全不进行发布操作");
        } else {
            for (CompanyAccountModel cam : accountModelList) {
                commit(cam.getAppId(), cam.getAccountType());
            }
            log.info("进行发布小程序");
        }
        return ResultModel.success();
    }

    @Async("asyncServiceExecutor")
    public void commit(String appId, Integer type) {
        VersionModel versionModel = versionMapper.select(new VersionModel() {{
            setVersionState(1);
            setVersionType(type);
        }});
        if (null != versionModel) {
            log.info("开始代码提交");
            codeService.commit(appId, versionModel.getVersionId(), true);
        }
    }

    /**
     *
     */
    @Autowired
    protected TemplateService templateService;

    @Async("asyncServiceExecutor")
    public void addTemplate(CompanyAccountModel model) {
        log.info("小程序微信模板添加：{}", model.toString());
        WxSubscribeEnums[] wxNoticeEnums = WxSubscribeEnums.values();
        log.info("wxNoticeEnums:{}",wxNoticeEnums);
        LoginEnum loginEnum = EnumUtil.getByIntegerTypeCode(LoginEnum.class, "getAccountType", model.getAccountType().toString());
        for (WxSubscribeEnums enums : wxNoticeEnums) {
            if (enums.getType().equals(loginEnum.getCode().toUpperCase())) {
                //查询消息是否存在
                WxNoticeModel wxNoticeModel = wxNoticeMapper.selectTempValue(new WxNoticeModel(){{
                    setMsgType(2);
                    setCompanyId(model.getCompanyId());
                    setCode(enums.getCode());
                    setType(enums.getType());
                }});
//                LibraryAddResponse libraryAddResponse = templateService.libraryAdd(model.getAppId(), enums.getNoticeId(), enums.getData());
                if(wxNoticeModel == null){
                    NewLibraryAddResponse libraryAddResponse = templateService.libraryAdd4Subscribe(model.getAppId(), enums.getNoticeId(), enums.getName(), enums.getKeywordIds());
                    if(libraryAddResponse.isSuccess()) {
                        wxNoticeModel = new WxNoticeModel();
                        wxNoticeModel.setCompanyId(model.getCompanyId());
                        wxNoticeModel.setWxNoticeName(enums.getName());
                        wxNoticeModel.setCode(enums.getCode());
                        wxNoticeModel.setValue(libraryAddResponse.getPriTmplId());
                        wxNoticeModel.setType(enums.getType());
                        wxNoticeModel.setPage(enums.getPage());
                        wxNoticeModel.setCreateTime(currentDate());
                        //消息类型 1模板消息，2订阅消息
                        wxNoticeModel.setMsgType(2);
                        wxNoticeMapper.insertSelective(wxNoticeModel);
                    }else{
                        log.info("wxNoticeModel_添加失败:{}",libraryAddResponse);
                    }
                }else{
                    log.info("已经存在:{}",wxNoticeModel);
                }
            }

        }
        //https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate
    }

    @Cacheable(value = RedisCode.REDIS_DB_CACHE)
    public CompanyAccountModel getCompanyAccountModel(String companyKey, Integer accountType) {
        CompanyAccountModel model1 = companyAccountMapper.select(new CompanyAccountModel() {{
            setCompanyKey(companyKey);
            setAccountType(accountType);
        }});
        if (null == model1) {
            log.info("未查到 company account 信息：{} {}", companyKey, accountType);
            return null;
        }
        return model1;
    }

    @Override
    @Cacheable(value = RedisCode.REDIS_DB_CACHE)
    public Map<String, String> getSubscribeTemplates(String companyKey, String accountType) {
        Integer aType;
        if (org.apache.commons.lang3.StringUtils.equalsIgnoreCase(LoginEnum.CRM.name(), accountType)) {
            aType = LoginEnum.CRM.getAccountType();
        } else if (org.apache.commons.lang3.StringUtils.equalsIgnoreCase(LoginEnum.USER.name(), accountType)) {
            aType = LoginEnum.USER.getAccountType();
        } else {
            aType = LoginEnum.USER.getAccountType();
        }
        CompanyAccountModel model1 = getCompanyAccountModel(companyKey, aType);
        if (null == model1) {
            log.info("未查到 company account 信息：{} {}", companyKey, aType);
            return null;
        }
        String realType = accountType;
        log.info("--------------- accountType : {} , companyKey : {}, companyId : {}", aType, companyKey, model1.getCompanyId());
        WxNoticeModel model = new WxNoticeModel() {
            {
                setCompanyId(model1.getCompanyId());
                setType(realType);
            }
        };
        List<WxNoticeModel> models = wxNoticeMapper.selectTemplates(model);
        if (model == null || models.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, String> templates = new HashMap<>(models.size());
        models.forEach(t -> {
            WxSubscribeEnums subscribeEnum = WxSubscribeEnums.getWxSubscribeEnums(t.getCode());
            templates.put(subscribeEnum.getAlias(), t.getValue());
        });
        return templates;
    }
}

